package me.leon.ext.android

import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo
import android.app.AppOpsManager
import android.app.usage.UsageStats
import android.app.usage.UsageStatsManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.os.Process
import android.provider.Settings
import android.util.Log
import androidx.core.content.FileProvider
import java.io.File
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.*
import kotlin.system.exitProcess
import me.leon.ext.Utils
import me.leon.ext.Utils.OnAppStatusChangedListener
import me.leon.ext.Utils.activityLifecycle
import me.leon.ext.Utils.activityList
import me.leon.ext.Utils.app
import me.leon.ext.java.HexUtils

/**
 * <pre> author: Blankj blog : http://blankj.com time : 2016/08/02 desc : utils about app </pre> *
 */
object AppUtils {
    /** The application's information. */
    data class AppInfo(
        var packageName: String? = null,
        var name: String? = null,
        var icon: Drawable? = null,
        var packagePath: String? = null,
        var versionName: String? = null,
        var versionCode: Int = 0,
        var isSystem: Boolean = false
    )

    /**
     * Register the status of application changed listener.
     *
     * @param obj The object.
     * @param listener The status of application changed listener
     */
    fun registerAppStatusChangedListener(obj: Any, listener: OnAppStatusChangedListener) {
        activityLifecycle.addOnAppStatusChangedListener(obj, listener)
    }

    /**
     * Unregister the status of application changed listener.
     *
     * @param obj The object.
     */
    fun unregisterAppStatusChangedListener(obj: Any) {
        activityLifecycle.removeOnAppStatusChangedListener(obj)
    }

    /**
     * Install the app.
     *
     * Target APIs greater than 25 must hold `<uses-permission
     * android:name="android.permission.REQUEST_INSTALL_PACKAGES" />`
     *
     * @param filePath The path of file.
     */
    fun installApp(filePath: String) {
        installApp(getFileByPath(filePath))
    }

    /**
     * Install the app.
     *
     * Target APIs greater than 25 must hold `<uses-permission
     * android:name="android.permission.REQUEST_INSTALL_PACKAGES" />`
     *
     * @param file The file.
     */
    fun installApp(file: File?) {
        if (!isFileExists(file)) return
        app.startActivity(getInstallAppIntent(file, true))
    }

    /**
     * Install the app.
     *
     * Target APIs greater than 25 must hold `<uses-permission
     * android:name="android.permission.REQUEST_INSTALL_PACKAGES" />`
     *
     * @param activity The activity.
     * @param filePath The path of file.
     * @param requestCode If &gt;= 0, this code will be returned in onActivityResult() when the
     * activity exits.
     */
    fun installApp(activity: Activity, filePath: String, requestCode: Int) {
        installApp(activity, getFileByPath(filePath), requestCode)
    }

    /**
     * Install the app.
     *
     * Target APIs greater than 25 must hold `<uses-permission
     * android:name="android.permission.REQUEST_INSTALL_PACKAGES" />`
     *
     * @param activity The activity.
     * @param file The file.
     * @param requestCode If &gt;= 0, this code will be returned in onActivityResult() when the
     * activity exits.
     */
    fun installApp(activity: Activity, file: File?, requestCode: Int) {
        if (!isFileExists(file)) return
        activity.startActivityForResult(getInstallAppIntent(file), requestCode)
    }

    /**
     * Uninstall the app.
     *
     * @param packageName The name of the package.
     */
    fun uninstallApp(packageName: String) {
        if (packageName.isNullOrEmpty()) return
        app.startActivity(getUninstallAppIntent(packageName, true))
    }

    /**
     * Uninstall the app.
     *
     * @param activity The activity.
     * @param packageName The name of the package.
     * @param requestCode If &gt;= 0, this code will be returned in onActivityResult() when the
     * activity exits.
     */
    fun uninstallApp(activity: Activity, packageName: String, requestCode: Int) {
        if (packageName.isNullOrEmpty()) return
        activity.startActivityForResult(getUninstallAppIntent(packageName), requestCode)
    }

    /**
     * Return whether the app is installed.
     *
     * @param pkgName The name of the package.
     * @return `true`: yes<br></br>`false`: no
     */
    fun isAppInstalled(pkgName: String): Boolean {
        val packageManager = app.packageManager
        return try {
            packageManager.getApplicationInfo(pkgName, 0) != null
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            false
        }
    }

    /**
     * Return whether it is a debug application.
     *
     * @return `true`: yes<br></br>`false`: no
     */
    val isAppDebug: Boolean
        get() = isAppDebug(app.packageName)

    /**
     * Return whether it is a debug application.
     *
     * @param packageName The name of the package.
     * @return `true`: yes<br></br>`false`: no
     */
    fun isAppDebug(packageName: String?): Boolean {
        return if (packageName.isNullOrEmpty()) false
        else
            try {
                val pm = app.packageManager
                val ai = pm.getApplicationInfo(packageName, 0)
                ai.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                false
            }
    }

    /**
     * Return whether it is a system application.
     *
     * @return `true`: yes<br></br>`false`: no
     */
    val isAppSystem: Boolean
        get() = isAppSystem(app.packageName)

    /**
     * Return whether it is a system application.
     *
     * @param packageName The name of the package.
     * @return `true`: yes<br></br>`false`: no
     */
    fun isAppSystem(packageName: String?): Boolean {
        return if (packageName.isNullOrEmpty()) false
        else
            try {
                val pm = app.packageManager
                val ai = pm.getApplicationInfo(packageName, 0)
                ai.flags and ApplicationInfo.FLAG_SYSTEM != 0
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                false
            }
    }

    /**
     * Return whether application is foreground.
     *
     * @return `true`: yes<br></br>`false`: no
     */
    val isAppForeground: Boolean
        get() = Utils.isAppForeground

    /**
     * Return whether application is foreground.
     *
     * Target APIs greater than 21 must hold `<uses-permission
     * android:name="android.permission.PACKAGE_USAGE_STATS" />`
     *
     * @param packageName The name of the package.
     * @return `true`: yes<br></br>`false`: no
     */
    fun isAppForeground(packageName: String): Boolean {
        return !packageName.isNullOrEmpty() && packageName == foregroundProcessName
    }

    /**
     * Return whether application is running.
     *
     * @param pkgName The name of the package.
     * @return `true`: yes<br></br>`false`: no
     */
    fun isAppRunning(pkgName: String): Boolean {
        val uid: Int
        val packageManager = app.packageManager
        uid =
            try {
                val ai = packageManager.getApplicationInfo(pkgName, 0) ?: return false
                ai.uid
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                return false
            }
        val am = app.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
        if (am != null) {
            val taskInfo = am.getRunningTasks(Int.MAX_VALUE)
            if (taskInfo != null && taskInfo.size > 0) {
                for (aInfo in taskInfo) {
                    if (pkgName == aInfo.baseActivity!!.packageName) {
                        return true
                    }
                }
            }
            val serviceInfo = am.getRunningServices(Int.MAX_VALUE)
            if (serviceInfo != null && serviceInfo.size > 0) {
                for (aInfo in serviceInfo) {
                    if (uid == aInfo.uid) {
                        return true
                    }
                }
            }
        }
        return false
    }

    /**
     * Launch the application.
     *
     * @param packageName The name of the package.
     */
    fun launchApp(packageName: String) {
        if (packageName.isNullOrEmpty()) return
        val launchAppIntent = getLaunchAppIntent(packageName, true)
        if (launchAppIntent == null) {
            Log.e("AppUtils", "Didn't exist launcher activity.")
            return
        }
        app.startActivity(launchAppIntent)
    }

    /**
     * Launch the application.
     *
     * @param activity The activity.
     * @param packageName The name of the package.
     * @param requestCode If &gt;= 0, this code will be returned in onActivityResult() when the
     * activity exits.
     */
    fun launchApp(activity: Activity, packageName: String, requestCode: Int) {
        if (packageName.isNullOrEmpty()) return
        val launchAppIntent = getLaunchAppIntent(packageName)
        if (launchAppIntent == null) {
            Log.e("AppUtils", "Didn't exist launcher activity.")
            return
        }
        activity.startActivityForResult(launchAppIntent, requestCode)
    }
    /**
     * Relaunch the application.
     *
     * @param isKillProcess True to kill the process, false otherwise.
     */
    /** Relaunch the application. */
    @JvmOverloads
    fun relaunchApp(isKillProcess: Boolean = false) {
        val intent = getLaunchAppIntent(app.packageName, true)
        if (intent == null) {
            Log.e("AppUtils", "Didn't exist launcher activity.")
            return
        }
        intent.addFlags(
            Intent.FLAG_ACTIVITY_NEW_TASK or
                Intent.FLAG_ACTIVITY_CLEAR_TOP or
                Intent.FLAG_ACTIVITY_CLEAR_TASK
        )
        app.startActivity(intent)
        if (!isKillProcess) return
        Process.killProcess(Process.myPid())
        System.exit(0)
    }
    /**
     * Launch the application's details settings.
     *
     * @param packageName The name of the package.
     */
    /** Launch the application's details settings. */
    @JvmOverloads
    fun launchAppDetailsSettings(packageName: String = app.packageName) {
        if (packageName.isNullOrEmpty()) return
        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
        intent.data = Uri.parse("package:$packageName")
        app.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
    }

    /** Exit the application. */
    fun exitApp() {
        val activityList: List<Activity> = activityList
        for (i in activityList.indices.reversed()) { // remove from top
            val activity = activityList[i]
            // sActivityList remove the index activity at onActivityDestroyed
            activity.finish()
        }
        exitProcess(0)
    }

    /**
     * Return the application's icon.
     *
     * @return the application's icon
     */
    val appIcon: Drawable?
        get() = getAppIcon(app.packageName)

    /**
     * Return the application's icon.
     *
     * @param packageName The name of the package.
     * @return the application's icon
     */
    fun getAppIcon(packageName: String?): Drawable? {
        return if (packageName.isNullOrEmpty()) null
        else
            try {
                val pm = app.packageManager
                val pi = pm.getPackageInfo(packageName, 0)
                pi?.applicationInfo?.loadIcon(pm)
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                null
            }
    }

    /**
     * Return the application's package name.
     *
     * @return the application's package name
     */
    val appPackageName: String
        get() = app.packageName

    /**
     * Return the application's name.
     *
     * @return the application's name
     */
    val appName: String?
        get() = getAppName(app.packageName)

    /**
     * Return the application's name.
     *
     * @param packageName The name of the package.
     * @return the application's name
     */
    fun getAppName(packageName: String? = app.packageName): String? {
        return if (packageName.isNullOrEmpty()) ""
        else
            try {
                val pm = app.packageManager
                val pi = pm.getPackageInfo(packageName, 0)
                pi?.applicationInfo?.loadLabel(pm)?.toString()
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                ""
            }
    }

    /**
     * Return the application's path.
     *
     * @return the application's path
     */
    val appPath: String?
        get() = getAppPath(app.packageName)

    /**
     * Return the application's path.
     *
     * @param packageName The name of the package.
     * @return the application's path
     */
    fun getAppPath(packageName: String?): String? {
        return if (packageName.isNullOrEmpty()) ""
        else
            try {
                val pm = app.packageManager
                val pi = pm.getPackageInfo(packageName, 0)
                pi?.applicationInfo?.sourceDir
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                ""
            }
    }

    /**
     * Return the application's version name.
     *
     * @return the application's version name
     */
    val appVersionName: String?
        get() = getAppVersionName(app.packageName)

    /**
     * Return the application's version name.
     *
     * @param packageName The name of the package.
     * @return the application's version name
     */
    fun getAppVersionName(packageName: String?): String? {
        return if (packageName.isNullOrEmpty()) ""
        else
            try {
                val pm = app.packageManager
                val pi = pm.getPackageInfo(packageName, 0)
                pi?.versionName
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                ""
            }
    }

    /**
     * Return the application's version code.
     *
     * @return the application's version code
     */
    val appVersionCode: Int
        get() = getAppVersionCode(app.packageName)

    /**
     * Return the application's version code.
     *
     * @param packageName The name of the package.
     * @return the application's version code
     */
    fun getAppVersionCode(packageName: String?): Int {
        return if (packageName.isNullOrEmpty()) -1
        else
            try {
                val pm = app.packageManager
                val pi = pm.getPackageInfo(packageName, 0)
                pi?.versionCode ?: -1
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                -1
            }
    }

    /**
     * Return the application's signature.
     *
     * @return the application's signature
     */
    val appSignature: Array<Signature>?
        get() = getAppSignature(app.packageName)

    /**
     * Return the application's signature.
     *
     * @param packageName The name of the package.
     * @return the application's signature
     */
    fun getAppSignature(packageName: String?): Array<Signature>? {
        return if (packageName.isNullOrEmpty()) null
        else
            try {
                val pm = app.packageManager
                @SuppressLint("PackageManagerGetSignatures")
                val pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
                pi?.signatures
            } catch (e: PackageManager.NameNotFoundException) {
                e.printStackTrace()
                null
            }
    }

    /**
     * Return the application's signature for SHA1 value.
     *
     * @return the application's signature for SHA1 value
     */
    val appSignatureSHA1: String
        get() = getAppSignatureSHA1(app.packageName)

    /**
     * Return the application's signature for SHA1 value.
     *
     * @param packageName The name of the package.
     * @return the application's signature for SHA1 value
     */
    fun getAppSignatureSHA1(packageName: String): String {
        return getAppSignatureHash(packageName, "SHA1")
    }

    /**
     * Return the application's signature for SHA256 value.
     *
     * @return the application's signature for SHA256 value
     */
    val appSignatureSHA256: String
        get() = getAppSignatureSHA256(app.packageName)

    /**
     * Return the application's signature for SHA256 value.
     *
     * @param packageName The name of the package.
     * @return the application's signature for SHA256 value
     */
    fun getAppSignatureSHA256(packageName: String) = getAppSignatureHash(packageName, "SHA256")

    /**
     * Return the application's signature for MD5 value.
     *
     * @return the application's signature for MD5 value
     */
    val appSignatureMD5: String
        get() = getAppSignatureMD5(app.packageName)

    /**
     * Return the application's signature for MD5 value.
     *
     * @param packageName The name of the package.
     * @return the application's signature for MD5 value
     */
    fun getAppSignatureMD5(packageName: String) = getAppSignatureHash(packageName, "MD5")

    /**
     * Return the application's user-ID.
     *
     * @return the application's signature for MD5 value
     */
    val appUid: Int
        get() = getAppUid(app.packageName)

    /**
     * Return the application's user-ID.
     *
     * @param pkgName The name of the package.
     * @return the application's signature for MD5 value
     */
    fun getAppUid(pkgName: String) =
        try {
            app.packageManager.getApplicationInfo(pkgName, 0).uid
        } catch (e: Exception) {
            e.printStackTrace()
            -1
        }

    private fun getAppSignatureHash(packageName: String, algorithm: String): String {
        if (packageName.isNullOrEmpty()) return ""
        val signature = getAppSignature(packageName)
        return if (signature.isNullOrEmpty()) ""
        else
            bytes2HexString(hashTemplate(signature[0].toByteArray(), algorithm))
                .replace("(?<=[0-9A-F]{2})[0-9A-F]{2}".toRegex(), ":$0")
    }

    /**
     * Return the application's information.
     *
     * * name of package
     * * icon
     * * name
     * * path of package
     * * version name
     * * version code
     * * is system
     *
     * @return the application's information
     */
    val appInfo: AppInfo?
        get() = getAppInfo(app.packageName)

    /**
     * Return the application's information.
     *
     * * name of package
     * * icon
     * * name
     * * path of package
     * * version name
     * * version code
     * * is system
     *
     * @param packageName The name of the package.
     * @return the application's information
     */
    fun getAppInfo(packageName: String): AppInfo? {
        return try {
            val pm = app.packageManager ?: return null
            getBean(pm, pm.getPackageInfo(packageName, 0))
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            null
        }
    }

    /**
     * Return the applications' information.
     *
     * @return the applications' information
     */
    val appsInfo: List<AppInfo>
        get() {
            val list: MutableList<AppInfo> = ArrayList()
            val pm = app.packageManager ?: return list
            val installedPackages = pm.getInstalledPackages(0)
            for (pi in installedPackages) {
                val ai = getBean(pm, pi) ?: continue
                list.add(ai)
            }
            return list
        }

    /**
     * Return the application's package information.
     *
     * @return the application's package information
     */
    fun getApkInfo(apkFile: File?): AppInfo? {
        return if (apkFile == null || !apkFile.isFile || !apkFile.exists()) null
        else getApkInfo(apkFile.absolutePath)
    }

    /**
     * Return the application's package information.
     *
     * @return the application's package information
     */
    fun getApkInfo(apkFilePath: String?): AppInfo? {
        if (apkFilePath.isNullOrEmpty()) return null
        val pm = app.packageManager ?: return null
        val pi = pm.getPackageArchiveInfo(apkFilePath, 0) ?: return null
        val appInfo = pi.applicationInfo
        appInfo.sourceDir = apkFilePath
        appInfo.publicSourceDir = apkFilePath
        return getBean(pm, pi)
    }

    private fun getBean(pm: PackageManager, pi: PackageInfo?): AppInfo? {
        if (pi == null) return null
        val ai = pi.applicationInfo
        val packageName = pi.packageName
        val name = ai.loadLabel(pm).toString()
        val icon = ai.loadIcon(pm)
        val packagePath = ai.sourceDir
        val versionName = pi.versionName
        val versionCode = pi.versionCode
        val isSystem = ApplicationInfo.FLAG_SYSTEM and ai.flags != 0
        return AppInfo(packageName, name, icon, packagePath, versionName, versionCode, isSystem)
    }

    ///////////////////////////////////////////////////////////////////////////
    // other utils methods
    ///////////////////////////////////////////////////////////////////////////
    private fun isFileExists(file: File?): Boolean {
        return file != null && file.exists()
    }

    private fun getFileByPath(filePath: String): File? {
        return if (filePath.isNullOrEmpty()) null else File(filePath)
    }

    private fun hashTemplate(data: ByteArray?, algorithm: String): ByteArray? {

        return if (data == null || data.isEmpty()) null
        else
            try {
                val md = MessageDigest.getInstance(algorithm)
                md.update(data)
                md.digest()
            } catch (e: NoSuchAlgorithmException) {
                e.printStackTrace()
                null
            }
    }

    private fun bytes2HexString(bytes: ByteArray?) = HexUtils.bytesToHexString(bytes)

    private fun getInstallAppIntent(file: File?): Intent {
        return getInstallAppIntent(file, false)
    }

    private fun getInstallAppIntent(file: File?, isNewTask: Boolean): Intent {
        val intent = Intent(Intent.ACTION_VIEW)
        val data: Uri
        val type = "application/vnd.android.package-archive"
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            data = Uri.fromFile(file)
        } else {
            val authority = app.packageName + ".utilcode.provider"
            data = FileProvider.getUriForFile(app, authority, file!!)
            intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        }
        app.grantUriPermission(app.packageName, data, Intent.FLAG_GRANT_READ_URI_PERMISSION)
        intent.setDataAndType(data, type)
        return if (isNewTask) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) else intent
    }

    private fun getUninstallAppIntent(packageName: String) =
        getUninstallAppIntent(packageName, false)

    private fun getUninstallAppIntent(packageName: String, isNewTask: Boolean): Intent {
        val intent = Intent(Intent.ACTION_DELETE)
        intent.data = Uri.parse("package:$packageName")
        return if (isNewTask) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) else intent
    }

    private fun getLaunchAppIntent(packageName: String) = getLaunchAppIntent(packageName, false)

    private fun getLaunchAppIntent(packageName: String, isNewTask: Boolean): Intent? {
        val launcherActivity = getLauncherActivity(packageName)
        if (launcherActivity.isNotEmpty()) {
            val intent = Intent(Intent.ACTION_MAIN)
            intent.addCategory(Intent.CATEGORY_LAUNCHER)
            val cn = ComponentName(packageName, launcherActivity)
            intent.component = cn
            return if (isNewTask) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) else intent
        }
        return null
    }

    private fun getLauncherActivity(pkg: String): String {
        val intent = Intent(Intent.ACTION_MAIN, null)
        intent.addCategory(Intent.CATEGORY_LAUNCHER)
        intent.setPackage(pkg)
        val pm = app.packageManager
        val info = pm.queryIntentActivities(intent, 0)
        val size = info.size
        if (size == 0) return ""
        for (i in 0 until size) {
            val ri = info[i]
            if (ri.activityInfo.processName == pkg) {
                return ri.activityInfo.name
            }
        }
        return info[0].activityInfo.name
    }

    // Access to usage information.
    private val foregroundProcessName: String?
        private get() {
            val am = app.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            val pInfo = am.runningAppProcesses
            if (pInfo != null && pInfo.size > 0) {
                for (aInfo in pInfo) {
                    if (aInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                        return aInfo.processName
                    }
                }
            }
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
                val pm = app.packageManager
                val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
                val list = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
                Log.i("ProcessUtils", list.toString())
                if (list.isEmpty()) {
                    Log.i(
                        "ProcessUtils",
                        "getForegroundProcessName: noun of access to usage information."
                    )
                    return ""
                }
                try { // Access to usage information.
                    val info = pm.getApplicationInfo(app.packageName, 0)
                    val aom = app.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
                    if (aom.checkOpNoThrow(
                            AppOpsManager.OPSTR_GET_USAGE_STATS,
                            info.uid,
                            info.packageName
                        ) != AppOpsManager.MODE_ALLOWED
                    ) {
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                        app.startActivity(intent)
                    }
                    if (aom.checkOpNoThrow(
                            AppOpsManager.OPSTR_GET_USAGE_STATS,
                            info.uid,
                            info.packageName
                        ) != AppOpsManager.MODE_ALLOWED
                    ) {
                        Log.i(
                            "ProcessUtils",
                            "getForegroundProcessName: refuse to device usage stats."
                        )
                        return ""
                    }
                    val usageStatsManager =
                        app.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager?
                    var usageStatsList: List<UsageStats>? = null
                    if (usageStatsManager != null) {
                        val endTime = System.currentTimeMillis()
                        val beginTime = endTime - 86400000 * 7
                        usageStatsList =
                            usageStatsManager.queryUsageStats(
                                UsageStatsManager.INTERVAL_BEST,
                                beginTime,
                                endTime
                            )
                    }
                    if (usageStatsList.isNullOrEmpty()) return null
                    var recentStats: UsageStats? = null
                    for (usageStats in usageStatsList) {
                        if (recentStats == null ||
                                usageStats.lastTimeUsed > recentStats.lastTimeUsed
                        ) {
                            recentStats = usageStats
                        }
                    }
                    return recentStats?.packageName
                } catch (e: PackageManager.NameNotFoundException) {
                    e.printStackTrace()
                }
            }
            return ""
        }
}
